import json

import requests
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.forms import model_to_dict
from django.urls import reverse
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt
from web.forms.file import FileFolderModelForm, FileModelForm
from web import models
from utils.cos import delete_file, delete_file_list, credential


def file(request, project_id):
    parent = None
    fid = request.GET.get('folder', '')
    if fid.isdecimal():
        parent = models.FileRepository.objects.filter(id=int(fid), project=request.tracer.project, file_type=2).first()
    if request.method == 'GET':
        form = FileFolderModelForm(request, parent)
        breadcrumb = []
        cur = parent
        while cur:
            # breadcrumb.insert(0, {'id': cur.id, 'name': cur.name})
            breadcrumb.insert(0, model_to_dict(cur, ['id', 'name']))
            cur = cur.parent
        query_set = models.FileRepository.objects.filter(project=request.tracer.project)
        if parent:
            file_list = query_set.filter(parent=parent).order_by('-file_type')
        else:
            file_list = query_set.filter(parent__isnull=True).order_by('-file_type')
        context = {'form': form, 'file_list': file_list, 'breadcrumb_list': breadcrumb, 'cur_folder': parent}
        return render(request, 'file.html', context)
    fid = request.POST.get('fid', '')
    obj = None
    if fid.isdecimal():
        obj = models.FileRepository.objects.filter(id=int(fid), project=request.tracer.project, file_type=2).first()
    if obj:
        form = FileFolderModelForm(request, parent, data=request.POST, instance=obj)
    else:
        form = FileFolderModelForm(request, parent, data=request.POST)
    if form.is_valid():
        form.instance.file_type = 2
        form.instance.project = request.tracer.project
        form.instance.update_user = request.tracer.user
        form.instance.parent = parent
        form.instance.update_datetime = timezone.now().astimezone(timezone.get_current_timezone())
        form.save()
        return JsonResponse({'status': True})
    return JsonResponse({'status': False, 'error': form.errors})


def file_delete(request, project_id):
    fid = request.GET.get('fid', '')
    if not fid.isdecimal():
        return JsonResponse({'status': False})
    delete_object = models.FileRepository.objects.filter(id=fid, project=request.tracer.project).first()
    if delete_object.file_type == 1:
        request.tracer.project.use_space -= delete_object.file_size
        request.tracer.project.save()
        delete_file(request.tracer.project.bucket, request.tracer.project.region, delete_object.key)
        delete_object.delete()
        return JsonResponse({'status': True})
    total_size = 0
    key_list = []
    folder_list = [delete_object, ]
    for folder in folder_list:
        child_list = models.FileRepository.objects.filter(project=request.tracer.project, parent=folder)
        for child in child_list:
            if child.file_type == 1:
                total_size += child.file_size
                key_list.append({'Key': child.key})
            else:
                folder_list.append(child)
    if key_list:
        delete_file_list(request.tracer.project.bucket, request.tracer.project.region, key_list)
        request.tracer.project.use_space -= total_size
        request.tracer.project.save()

    delete_object.delete()
    return JsonResponse({'status': True})


@csrf_exempt
def cos_credential(request, project_id):
    per_file_limit = request.tracer.price_policy.per_file_size * 1024 * 1024
    total_file_limit = request.tracer.price_policy.project_space * 1024 * 1024 * 1024
    total_size = 0
    file_list = json.loads(request.body.decode('utf-8'))
    for file in file_list:
        if file['size'] > per_file_limit:
            return JsonResponse({'status': False,
                                 'error': '单文件超出限制(最大{}M)，文件:{} 请升级套餐'.format(
                                     request.tracer.price_policy.per_file_size,
                                     file['name'])})

        total_size += file['size']
    if total_size + request.tracer.project.use_space > total_file_limit:
        return JsonResponse({'status': False,
                             'error': '该项目文件大小已超出限制(最大{}G)!'.format(
                                 request.tracer.price_policy.project_space)})

    data_dict = credential(request.tracer.project.bucket, request.tracer.project.region)
    return JsonResponse({'status': True, 'data': data_dict})


@csrf_exempt
def file_post(request, project_id):
    form = FileModelForm(request, data=request.POST)
    if form.is_valid():
        # 校验通过
        data_dict = form.cleaned_data
        data_dict.pop('etag')
        data_dict.update({'project': request.tracer.project, 'file_type': 1, 'update_user': request.tracer.user})
        data_dict['update_datetime'] = timezone.now().astimezone(timezone.get_current_timezone())
        instance = models.FileRepository.objects.create(**data_dict)
        # 项目的已使用空间更新
        request.tracer.project.use_space += data_dict['file_size']
        request.tracer.project.save()

        result = {
            'id': instance.id,
            'name': instance.name,
            'file_size': instance.file_size,
            'username': instance.update_user.username,
            'datetime': instance.update_datetime.strftime('%Y年%m月%d日 %H:%M'),
            'file_type': instance.get_file_type_display(),
            'download_url': reverse('file_download', kwargs={'project_id': project_id, 'file_id': instance.id})
        }
        return JsonResponse({'status': True, 'data': result})

    return JsonResponse({'status': False, 'error': form.errors})


def file_download(request, project_id, file_id):
    file_object = models.FileRepository.objects.filter(project_id=project_id, id=file_id).first()
    res = requests.get(file_object.file_path)
    data = res.content
    response = HttpResponse(data)
    response['Content-Disposition'] = "attachment;filename={}".format(file_object.name)
    return response
